package thmp.parse;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.util.List;
import java.util.Set;

import thmp.parse.ParseState.ParseStateBuilder;
import thmp.search.SearchState;
import thmp.utils.FileUtils;

/**
 * Generate relational context vector, i.e. instances of RelationVec.
 * @author yihed
 *
 */
public class GenerateRelationVec {

	private static final String serializeFileName = "src/thmp/data/AllThmsRelationVecs.dat";
	private static final boolean WRITE_UNKNOWNWORDS = false;
	
	/**
	 * Generate relational vector based on the query String.
	 * @param queryStr
	 * @param parseState
	 * @return
	 */
	public static Set<Integer> generateRelationVec(String queryStr, SearchState searchState){
		
		ParseState parseState = searchState.getParseState();
		//if not null, then already contains queryStr parse generated by previous searcher
		//e.g. contextSearcher.
		if(null == parseState){
			ParseStateBuilder parseStateBuilder = new ParseStateBuilder();
			parseStateBuilder.setWriteUnknownWordsToFile(WRITE_UNKNOWNWORDS);
			parseState = parseStateBuilder.build();
			boolean isVerbose = true;
			ParseRun.parseInput(queryStr, parseState, isVerbose);			
		}
		searchState.setParseState(parseState);
		return parseState.getRelationalContextVec();		
	}
	
	/**
	 * Back up vector, if generateRelationVec() did not set anything, now
	 * assume all relations are set, since none was specified.
	 * Actually should just skip searching this way if no good vector produced.
	 * @return
	 */
	/*public static BigInteger generateBackupRelationVec(String queryStr){
		
		setBitPosList(String termStr, List<Integer> bitPosList, int modulus, 
				RelationType posTermRelationType, boolean isParseStructTypeHyp);		
		fillByteArray(byte[] byteArray, List<Integer> bitPosList);		
	}*/
	
	public static void main(String[] args){
		
		//parseAndSerializeThms();
		
		//test deserialization
		//System.out.println("Deserialized relation vectors: " + deserializeRelationVecList());
	}
	
	private static void serializeRelationVecList(List<BigInteger> relationVecList){
		
		FileOutputStream fo = null;
		ObjectOutputStream oo = null;		
		try{
			fo = new FileOutputStream(serializeFileName);
			oo = new ObjectOutputStream(fo);		
			oo.writeObject(relationVecList);
		}catch(IOException e){
			e.printStackTrace();
		}finally{
			FileUtils.silentClose(oo);
			FileUtils.silentClose(fo);
		}		
	}
	
	/**
	 * Deserializes the relationVecList.
	 */
	@SuppressWarnings("unchecked")
	private static List<BigInteger> deserializeRelationVecList(){
		
		List<BigInteger> relationVecList = null;
		
		FileInputStream fileInputStream = null;
		ObjectInputStream objectInputStream = null;
		
		try{
			fileInputStream = new FileInputStream(serializeFileName);
			objectInputStream = new ObjectInputStream(fileInputStream);
		}catch(FileNotFoundException e){
			e.printStackTrace();
			FileUtils.silentClose(fileInputStream);
			FileUtils.silentClose(objectInputStream);
			throw new IllegalStateException("relation vectors file not found " + e);
		}catch(IOException e){
			e.printStackTrace();
			FileUtils.silentClose(fileInputStream);
			FileUtils.silentClose(objectInputStream);
			throw new IllegalStateException("IOException while creating ObjectInputStream " + e);
		}		
		
		try{
			Object o = objectInputStream.readObject();
			
			relationVecList = (List<BigInteger>)o;
			
		}catch(IOException e){
			e.printStackTrace();
			throw new IllegalStateException("IOException while reading object. " + e);	
		}catch(ClassNotFoundException e){
			e.printStackTrace();
			throw new IllegalStateException("Class not found while reading object. " + e);
		}finally{
			FileUtils.silentClose(fileInputStream);
			FileUtils.silentClose(objectInputStream);
		}
		return relationVecList;
	}
	
}
